package org.zdc.io;
import haxe.io.Error;
#if neko
import neko.Lib;
#elseif cpp
import cpp.Lib;
#end
import sys.FileSystem;

/**
 * 类似lisp的pathname
 * @author simple slime
 */

using StringTools;
using org.zdc.ZArray;

class ZPath 
{
	public static inline var DIRECTORY = 1;
	public static inline var FILE = 2;
	public static inline var FILE_AND_DIRECTORY = 3;
	
	public var host(getHost, null):String;
	public var device(getDevice, null):String;
	public var name(getName, null):String;
	public var fname(getFname, null):String;
	public var type(getType, null):String;
	public var version(getVersion, null):String;
	public var dir(getDir, null):String;
	public var fdir(getFdir, null):String;
	public var abs(getAbs, null):Bool;
	public var isDir(getIsDirectory, null):Bool;
	public var fpath(getPath, null):String;
	
	private var _host = "";
	private var _device = "";
	private var _name = "";
	private var _fname = "";
	private var _type = "";
	private var _version = "";
	private var _dir = "";
	private var _fdir = "";
	private var _fpath = "";
	private var _abs = false;
	private var _head = "";
	private var _isDir = false;
	
	public function new(path:String) 
	{
		path = path.trim();
		//删除最后的\或/
		path = ~/(\/|\\)$/.replace(path, "");  					//Lib.println(Std.format("path: ${ path }"));
		var dirs:Array<String> = ~/\\|\//gi.split(path);
		
		//windows
		if (~/\S+(\\|\/)*:/gi.match(dirs[0])) {
			_device = dirs.shift();
			_abs = true;
		}
		//xnix
		else if(~/^\//.match(path)){
			_abs = true;
		}
		else {
			_abs = false;
		}
		
		{
			_fdir = path;
			if (!_abs) {
				_fdir = Sys.getCwd() + "/" + _fdir;
			}
			if (isDirectory(_fdir)) {
				_isDir = true;
			}
			else {
				_fdir = _fdir.replace(dirs.last(), "");
				_fdir = _fdir.substr(0, _fdir.length - 1);			//Lib.println("change!:" + fdir);
				_isDir = false;
			}
		}
		
		if (_isDir) {
			_type = "";
			_dir = path;
			_name = dirs.last();
		}
		else {
			_fname = dirs.last();					//Lib.println("fname:" + _fname + ", dir = " + dirs);
			dirs.pop();					
			_dir = _device + "/" + dirs.join("/");			
			var reg = ~/(.+)\.(\S+?)$/gi;
			if (reg.match(_fname)) {				//Lib.println("matched!");
				_name = reg.matched(1);
				_type = reg.matched(2);
			}
			else {
				_name = _fname;
				_type = "";
			}
		}
		
		_fpath = _fdir + "/" + _fname;
	}
	
	function getHost():String {
		return _host;
	}
	
	function getDevice():String {
		return _device;
	}
	
	function getName():String {
		return _name;
	}
	
	function getFname():String {
		return _fname;
	}
	
	function getType():String {
		return _type;
	}
	
	function getVersion():String {
		return _version;
	}
	
	function getDir():String {
		return _dir;
	}
	
	function getFdir():String {
		return _fdir;
	}
	
	function getIsDirectory():Bool {
		return _isDir;
	}
	
	function getAbs():Bool {
		return _abs;
	}
	
	function getPath():String {
		return _fpath;
	}
	
	/**
	 * rename a file
	 * @param	newpath
	 */
	public function rename(newpath:String):Void {
		Lib.println("fpath: " + fpath);
		FileSystem.rename(fpath, newpath);
	}
	
	/**
	 * copy a file
	 * @param	newname
	 */
	public function copy(newname:String):Void {
		Sys.command("copy", [fpath, _fdir + "/" + newname]);
	}
	
	/**
	 * delete a file
	 */
	public function delete():Void {
		_isDir? FileSystem.deleteDirectory(fpath) : FileSystem.deleteFile(fpath);
	}
	
	/**
	 * check is a path is a directory
	 * @param	path
	 */
	public static function isDirectory(path:String):Bool {
		try {			
			return FileSystem.isDirectory(path);
		}
		catch (msg:Dynamic) {
			return false;
		}
	}
	
	public function toString():String {
		return Std.format("[ZPath fpath = ${ fpath }, fname = ${ _fname }, name = ${ _name }, type = ${ _type }, dir = ${ _dir }, fdir = ${ _fdir }, device = ${ _device }, isDir = ${ _isDir }]");
	}
}